import json
import re

from django import http
from django.contrib.auth import login, logout, authenticate
from django.shortcuts import render, redirect
# Create your views here.
from django.urls import reverse
from django.views import View

from carts.utils import merge_cart_cookie_to_redis
from celery_tasks.email.tasks import send_email
from goods.models import SKU
from meiduo_mall.utils.response_code import RETCODE
from meiduo_mall.utils.view import LoginRequiredMixin
from users.models import User
from django_redis import get_redis_connection
import logging
logger = logging.getLogger('django')


class RegisterView(View):
    def get(self, request):

        return render(request, 'register.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')
        sms_code = request.POST.get('sms_code')

        if not all([username, password, password2, mobile, allow]):
            return http.HttpResponseForbidden('请填写完整')

        if not re.match('^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('用户名格式不正确')

        if not re.match('^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码格式不正确')

        if password != password2:
            return http.HttpResponseForbidden('两次密码不相同')

        if not re.match('^1[345789]\d{9}$', mobile):
            return http.HttpResponseForbidden('手机号格式不正确')

        if allow != 'on':
            return http.HttpResponseForbidden('请勾选协议')

        redis_conn = get_redis_connection('verify_code')

        tiqu = redis_conn.get(mobile)
        if tiqu == None:
            return render(request, 'register.html', {'errmsg': '短信验证码已过期'})

        if tiqu.decode() != sms_code:
            return render(request, 'register.html', {'errmsg': '短信验证码不正确'})

        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception:
            return render(request, 'register.html', {'errmsg': '注册失败'})

        login(request, user)

        response = redirect(reverse('center:index'))

        response.set_cookie('username', user.username, max_age=3600 * 24 * 14)

        return response


class UsernameCount(View):
    def get(self, request, username):
        count = User.objects.filter(username=username).count()

        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'count': count})


class MobileCount(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()

        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'count': count})


class LoginView(View):
    def get(self, request):

        return render(request, 'login.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        if not all([username, password]):
            return http.HttpResponseBadRequest('请填写完整')

        if not re.match('^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('用户名格式不正确')

        if not re.match('^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('密码格式不正确')

        try:
            user = authenticate(username=username, password=password)
        except Exception:
            return http.HttpResponseBadRequest('数据库对比失败')

        if user is None:
            return render(request, 'login.html', {'accont_errmsg': '用户名或者密码错误'})

        login(request, user)

        if remembered != 'on':
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(None)

        next = request.GET.get('next')

        if next:
            response = redirect(next)

        else:
            response = redirect(reverse('center:index'))

        response.set_cookie('username', user.username, 3600 * 24 * 14)

        response = merge_cart_cookie_to_redis(request, response, user)

        return response


class LogoutView(View):
    def get(self, request):
        logout(request)

        response = redirect(reverse('center:index'))

        response.delete_cookie('username')

        return response


class UserInfo(LoginRequiredMixin, View):
    def get(self, request):
        if request.user.is_authenticated():
            context = {
                'username': request.user.username,
                'mobile': request.user.mobile,
                'email': request.user.email,
                'email_active': request.user.email_active
            }
            return render(request, 'user_center_info.html', context)
        else:
            return redirect(reverse('users:login'))


class EmailView(LoginRequiredMixin, View):
    def put(self, request):
        email_dict = request.body.decode()
        email = json.loads(email_dict)
        email = email.get('email')

        # 校验参数
        if not email:
            return http.HttpResponseForbidden('请填写邮箱')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return http.HttpResponseForbidden('邮箱格式不正确')
        # 赋值 email 字段
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR,
                                      'errmsg': '邮箱添加失败'})
        # 异步发送验证邮件
        email_url = request.user.generate_email_url()
        send_email.delay(email, email_url)
        # 响应添加邮箱结果
        return http.JsonResponse({'code': RETCODE.OK,
                                  'errmsg': '邮箱添加成功'})


class VerifyEmailView(View):
    def get(self, request):
        # 接收参数
        token = request.GET.get('token')
        # 校验参数：判断 token 是否为空和过期，提取 user
        if not token:
            return http.HttpResponseForbidden('token为空')
        # 调用上面封装好的方法, 将 token 传入
        user = User.check_email_token(token)
        if not user:
            return http.HttpResponseForbidden('无效的token')
        # 修改 email_active 的值为 True
        try:
            user.email_active = True
            user.save()
        except Exception as e:
            logger.error(e)
            return http.HttpResponseForbidden('邮件激活失败')
        # 返回邮箱验证结果
        return redirect(reverse('users:info'))


class PasswordView(View):
    def get(self, request):

        return render(request, 'user_center_pass.html')

    def post(self, request):
        old_password = request.POST.get('old_password')
        new_password = request.POST.get('new_password')
        new_password2 = request.POST.get('new_password2')

        if not all([old_password, new_password, new_password2]):
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            request.user.check_password(old_password)
        except Exception as e:
            logger.error(e)
            return render(request, 'user_center_pass.html', {'origin_pwd_errmsg': '原始密码错误'})
        if not re.match(r'^[0-9A-Za-z]{8,20}$', new_password):
            return http.HttpResponseForbidden('密码最少8位，最长20位')
        if new_password != new_password2:
            return http.HttpResponseForbidden('两次输入的密码不一致')

        try:
            request.user.set_password(new_password)
            request.user.save()
        except Exception as e:
            logger.error(e)
            return render(request, 'user_center_pass.html', {'change_pwd_errmsg': '修改密码失败'})

        logout(request)
        response = redirect(reverse('users:login'))
        response.delete_cookie('username')

        return response


class UserBrowseView(LoginRequiredMixin, View):
    def post(self, request):
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')

        try:
            SKU.objects.get(id=sku_id)
        except Exception:
            return http.HttpResponseForbidden('商品不存在')

        user_id = request.user.id

        redis_conn = get_redis_connection('history')

        pl = redis_conn.pipeline()

        pl.lrem('history_%s' % user_id, 0, sku_id)
        pl.lpush('history_%s' % user_id, sku_id)
        pl.trim('history_%s' % user_id, 0, 4)

        pl.execute()

        return http.JsonResponse({'code': RETCODE.OK,
                                  'errmsg': 'ok'})

    def get(self, request):
        redis_conn = get_redis_connection('history')
        skusss = redis_conn.lrange('history_%s' % request.user.id, 0, -1)

        skus = []

        for sku_id in skusss:
            sku = SKU.objects.get(id=sku_id)
            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image_url,
                'price': sku.price
            })

        return http.JsonResponse({'code': RETCODE.OK,
                                  'errmsg': 'ok',
                                  'skus': skus})